home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / compstol / cmpsttl1.lha / CompositeTool / v1.1.dist / HDF / dfimcomp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-08  |  34.5 KB  |  1,229 lines

  1. /*****************************************************************************
  2. *              NCSA HDF version 3.00
  3. *                December, 1989
  4. *
  5. * NCSA HDF Version 3.00 source code and documentation are in the public
  6. * domain.  Specifically, we give to the public domain all rights for future
  7. * licensing of the source code, all resale rights, and all publishing rights.
  8. * We ask, but do not require, that the following message be included in all
  9. * derived works:
  10. * Portions developed at the National Center for Supercomputing Applications at
  11. * the University of Illinois at Urbana-Champaign.
  12. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  13. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  14. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  15. *****************************************************************************/
  16.  
  17. /************************************************************************/
  18. /*  Module Name : imcomp                        */
  19. /*  Exports     : DFCimcomp(), DFCunimcomp()                */
  20. /*  Purpose     : Compresses color images               */
  21. /*  Author  : Eng-Kiat Koh                      */
  22. /*  Date    : June 30th, 1988                   */
  23. /*  Functions   : DFCimcomp(), compress(), init_global(), cnt_color()   */
  24. /*        set_palette(), fillin_color(), map(), nearest_color() */
  25. /*        DFCunimcomp(), sqr()                                  */
  26. /************************************************************************/
  27.  
  28.  
  29. #include "df.h"
  30.  
  31. #define PALSIZE 256
  32. #define BIT8 0
  33. #define BIT24 1
  34.  
  35. #ifndef MAC
  36. #define MAXCOLOR 32768
  37. #else /*MAC*/
  38. #define MAXCOLOR 768
  39. #endif /*MAC*/
  40.  
  41. #define RED 0
  42. #define GREEN 1
  43. #define BLUE 2
  44. #define EPSILON 0.5
  45. #define LO 1
  46. #define HI 0
  47.  
  48. struct rgb
  49. {
  50.   char c[3];
  51. };
  52.  
  53. struct box
  54. {
  55.   float bnd[3][2];
  56.   int *pts;
  57.   int nmbr_pts;
  58.   int nmbr_distinct;
  59.   struct box *left;
  60.   struct box *right;
  61. };
  62.  
  63.  
  64. char *new_pal;          /* pointer to new palette           */
  65.  
  66.  
  67. static int *hist;                /* histogram for distinct colors    */
  68. static struct box *frontier;     /* pointer to the list of boxes     */
  69. static struct rgb *distinct_pt;  /* contains all distinct rgb points */
  70.  
  71. static void sel_palette();
  72. static void compress();
  73. static void init_global();
  74. static int cnt_color();
  75. static void set_palette();
  76. static void fillin_color();
  77. static int indx();
  78. static void map();
  79. static int nearest_color();
  80. static long int sqr();
  81. static void init();
  82. static int partition();
  83. static struct box *find_box();
  84. static void split_box();
  85. static void assign_color();
  86. static int select_dim();
  87. static float find_med();
  88. static void classify();
  89. static int next_pt();
  90.  
  91. extern char *calloc();
  92.  
  93. static struct rgb *color_pt;    /* contains the hi-lo colors for each block */
  94. static char *image;        /* contains the compressed image            */
  95. static int trans[MAXCOLOR];     /* color translation table                  */
  96.  
  97. /************************************************************************/
  98. /*  Function    : DFCimcomp                                             */
  99. /*  Purpose : Performs Imcomp Compression                           */
  100. /*  Parameters  :                                                       */
  101. /*    xdim, ydim - dimensions of image                                  */
  102. /*                 IT IS ASSUMED THAT THE DIMENSIONS ARE A MULTIPLE OF 4*/
  103. /*    in, out    - input image array and output image buffer size of in */
  104. /*                 is xdim*ydim bytes for 8 bit per pixel mode. It is 3 */
  105. /*                 times that for 24 bits per pixel mode. The output    */
  106. /*                 buffer is always (xdim*ydim)/4.                      */
  107. /*    in_pal     - input palette. Consist of rgb triples unlike seq-type*/
  108. /*                 palette. This is a NULL pointer if operating at the  */
  109. /*                 24 bit per pixel mode.                               */
  110. /*    out_pal    - output palette. Consist of PALSIZE color entries.    */
  111. /*                 each entry is an rgb triple.                         */
  112. /*    mode       - Either BIT8 or BIT24                                 */
  113. /*  Returns     : none                          */
  114. /*  Called by   : External routines                                     */
  115. /*  Calls       : init_global(), compress(), cnt_color(), set_palette(),*/
  116. /*        sel_palette(), map()                                  */
  117. /************************************************************************/
  118.  
  119. void DFCimcomp(xdim, ydim, in, out, in_pal, out_pal, mode)
  120. int32 xdim, ydim;
  121. int mode;
  122. char in[], out[], in_pal[], out_pal[];
  123. {
  124.   char raster[48];
  125.   int blocks, nmbr, i, j, k, l, x, y;
  126.   void init_global();
  127.   void compress();
  128.   int cnt_color();
  129.   void set_palette();
  130.   void sel_palette();
  131.   void map();
  132.   void fillin_color();
  133.  
  134.   init_global(xdim, ydim, out, out_pal);
  135.  
  136.   /* compress pixel blocks */
  137.   blocks = 0;
  138.   for (i=0; i<(ydim/4); i++)
  139.     for (j=0; j<(xdim/4); j++)
  140.     {
  141.       switch (mode)
  142.       {
  143.         case BIT8 : /* 8 bit per pixel format */
  144.             k = 0;
  145.             for (y=(i*4); y<(i*4+4); y++)
  146.               for (x=(j*4); x<(j*4+4); x++)         
  147.               {
  148.             l = y*xdim + x;
  149.             raster[k++] = in_pal[3*in[l]];
  150.             raster[k++] = in_pal[3*in[l]+1];
  151.             raster[k++] = in_pal[3*in[l]+2];
  152.               } /* end of for x */
  153.             compress(raster,blocks);
  154.             break;
  155.  
  156.     case BIT24: /* 24 bit per pixel format */
  157.             k = 0;
  158.             for (y=(i*4); y<(i*4+4); y++)
  159.               for (x=(j*4); x<(j*4+4); x++)         
  160.               {
  161.             l = 3 *(y*xdim + x);
  162.             raster[k++] = in[l];
  163.             raster[k++] = in[l+1];
  164.             raster[k++] = in[l+2];
  165.               } /* end of for x */
  166.             compress(raster,blocks);
  167.             break;
  168.     
  169.     default   : /* unsupported format */
  170.             printf("Error : Unsupported Format \n");
  171.             exit(1);
  172.             break;
  173.       } /* end of switch */
  174.       
  175.       blocks++;
  176.     } /* end of for j */
  177.  
  178.   /* set palette */
  179.   nmbr = cnt_color(blocks);
  180. /*
  181.   printf("Number of colors %d \n", nmbr);
  182. */
  183.   if (nmbr <= PALSIZE)
  184.     set_palette(blocks);
  185.   else
  186.   {
  187.     sel_palette(blocks,nmbr,color_pt);
  188.     map(blocks);
  189.   }
  190.  
  191.   fillin_color(blocks);
  192.  
  193. } /* end of DFCimcomp */
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200. /************************************************************************/
  201. /*  Function    : compress                                  */
  202. /*  Purpose : Given a block of 16 pixels, sets up a 16 bit bitmap   */
  203. /*                and assigns a lo and hi color for the block. For block*/
  204. /*                i, hi color is stored in color_pt[2i] and lo in       */
  205. /*                color_pt[2i+1]. Each color is then reduced to 15 bits */
  206. /*                by truncating the lower order 3 bits of each component*/
  207. /*  Parameter   :                           */
  208. /*    raster     - contains the 16 pixels of a block. Each pixel is 3   */
  209. /*         bytes, 1 byte for each color component               */
  210. /*    block  - pixel block number                                   */
  211. /*  Returns     : none                                                  */
  212. /*  Called by   : DFCimcomp()                       */
  213. /*  Calls       : none                          */
  214. /************************************************************************/
  215.  
  216. static void compress(raster, block)
  217. char raster[];
  218. int block;
  219. {
  220.   float y[16], y_av;
  221.   int i, j, k, l, bit;
  222.   int high, hi, lo;
  223.   int c_hi[3], c_lo[3];
  224.  
  225.   /* calculate luminance */
  226.   y_av = 0.0;
  227.   for (i=0; i<16; i++)
  228.   {
  229.     j = 3*i;
  230.     y[i] = 0.3*(float)raster[j] + 0.59*(float)raster[j+1] + 
  231.            0.11*(float)raster[j+2];
  232. /*    printf("compress: y[%d] is %f\n",i,y[i]);*/
  233.     y_av = y_av + y[i];
  234.   }
  235.   y_av = y_av / 16.0;
  236. /*  printf("y_av is %f\n",y_av); */
  237.  
  238.   /* initialize c_hi and c_lo */
  239.   for (i=RED; i<=BLUE; i++)
  240.   {
  241.     c_hi[i] = 0;
  242.     c_lo[i] = 0;
  243.   }
  244.  
  245.   /* build bit map */
  246.   k = 4 * block;
  247.   high = 0;
  248.   hi = 2 * block;
  249.   lo = hi + 1;
  250.   for (i=0; i<2; i++)
  251.   {
  252.     bit = 128;
  253.     for (j = (i*8); j<(i*8+8); j++)
  254.     {
  255.       if (y[j] > y_av)
  256.       {
  257.     image[k] = image[k] | bit;
  258.     high++;
  259.         for (l=RED; l<= BLUE; l++)
  260.       c_hi[l] = c_hi[l] + (int)raster[3*j+l];
  261.       }
  262.       else
  263.       {
  264.     for (l=RED; l<=BLUE; l++)
  265.           c_lo[l] = c_lo[l] + (int)raster[3*j+l];
  266.       } /* end of if */
  267.  
  268.       bit = bit >> 1;
  269.     } /* end of for j */
  270.    
  271.     k++;
  272.   } /* end of for i */
  273.  
  274.   /* calculate hi lo color */
  275.   for (i=RED; i<=BLUE; i++)
  276.   {
  277.     if (high != 0)
  278.       color_pt[hi].c[i] = (int)((float)c_hi[i] / (float)high);
  279.     if (high != 16)
  280.       color_pt[lo].c[i] = (int)((float)c_lo[i] / (float)(16 - high));
  281.     color_pt[hi].c[i] = color_pt[hi].c[i] >> 3;
  282.     color_pt[lo].c[i] = color_pt[lo].c[i] >> 3;
  283.  
  284.   }
  285. } /* end of compress */
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292. /************************************************************************/
  293. /*  Function    : init_global                       */
  294. /*  Purpose : Allocates memory for global variables                 */
  295. /*  Parameter   :                           */
  296. /*    xdim, ydim - x and y dimension of image               */
  297. /*    out        - pointer to output buffer                             */
  298. /*    out_pal    - pointer to output palette                            */
  299. /*  Returns     : none                              */
  300. /*  Called by   : DFCimcomp()                       */
  301. /*  Calls       : none                          */
  302. /************************************************************************/
  303.  
  304. static void init_global(xdim, ydim, out, out_pal)
  305. int32 xdim, ydim;
  306. char *out, *out_pal;
  307. {
  308.   int i, j;
  309.  
  310.   /* allocate memory */
  311.   image = out;
  312.   new_pal = out_pal;
  313.   color_pt = (struct rgb *)calloc((unsigned)((xdim*ydim)/8),
  314.          sizeof(struct rgb));
  315.  
  316.   if (image == NULL || color_pt == NULL || new_pal == NULL)
  317.   {
  318.     printf("Error : Out of Memory\n");
  319.     exit(1);
  320.   }
  321.  
  322.   /* initialize */
  323.   for (i=0; i<(xdim*ydim/4); i++)
  324.     image[i] = 0;
  325.  
  326.   for (i=0; i<(xdim*ydim/8); i++)
  327.     for (j=RED; j<= BLUE; j++)
  328.       color_pt[i].c[j] = 0;
  329.  
  330.   for (i=0; i<MAXCOLOR; i++)
  331.     trans[i] = -1;
  332. } /* end of init_global */
  333.  
  334.  
  335.  
  336.  
  337.  
  338. /************************************************************************/
  339. /*  Function    : cnt_color                                 */
  340. /*  Purpose : Counts the number of distinct colors compressd image  */
  341. /*  Parameter   :                           */
  342. /*    blocks     - total number of pixel blocks             */
  343. /*  Returns     : Number of distinct colors                             */
  344. /*  Called by   : DFCimcomp()                                           */
  345. /*  Calls       : indx()                        */
  346. /************************************************************************/
  347.  
  348. static int cnt_color(blocks)
  349. int blocks;
  350. {
  351.   int temp[MAXCOLOR];
  352.   int i, k, count;
  353.   int indx();
  354.  
  355.   for (i=0; i<MAXCOLOR; i++)
  356.     temp[i] = -1;
  357.  
  358.   for (i=0; i<(2*blocks); i++)
  359.   {
  360.     k = indx(color_pt[i].c[RED],color_pt[i].c[GREEN],color_pt[i].c[BLUE]);
  361. /*    printf("cnt_color: k is %d\n",k); */
  362.     temp[k] = 0;
  363.   }
  364.  
  365.   count  = 0;
  366.   for (i = 0; i< MAXCOLOR; i++)
  367.     if (temp[i] == 0)
  368.       count++;
  369.  
  370.   return count;
  371. } /* end of cnt_color */
  372.  
  373.  
  374.  
  375.  
  376.  
  377. /************************************************************************/
  378. /*  Function    : set_palette                       */
  379. /*  Purpose : The number of distinct colors is less than the desired*/
  380. /*                output palette size. Therefore each distinct color can*/
  381. /*        be a palette entry. Function enters each distinct     */
  382. /*                color as a palette entry and sets up the translation  */
  383. /*                table. It also shifts each color component left 3 bits*/
  384. /*                so that each color component is again 8 bits wide     */
  385. /*  Parameter   :                           */
  386. /*    blocks     - total number of pixel blocks                         */
  387. /*  Returns     : none                          */
  388. /*  Called by   : DFCimcomp()                       */
  389. /*  Calls       : indx()                        */
  390. /************************************************************************/
  391.  
  392. static void set_palette(blocks)
  393. int blocks;
  394. {
  395.   int ent, i, k;
  396.   int indx();
  397.  
  398.   ent = 0;
  399.   for (i = 0; i<(2*blocks); i++)
  400.   {
  401.     k = indx(color_pt[i].c[RED],color_pt[i].c[GREEN],color_pt[i].c[BLUE]);
  402.     if (trans[k] == -1)
  403.     {
  404.       new_pal[3*ent] = color_pt[i].c[RED] << 3;
  405.       new_pal[3*ent+1] = color_pt[i].c[GREEN] << 3;
  406.       new_pal[3*ent+2] = color_pt[i].c[BLUE] << 3;  
  407.       trans[k] = ent;
  408.       ent++;
  409.     }
  410.   }
  411. } /* end of set_palette */
  412.  
  413.  
  414.  
  415.  
  416.  
  417. /************************************************************************/
  418. /*  Function    : fillin_color                      */
  419. /*  Purpose : For each pixel block, fills in the pointers into the  */
  420. /*                palette.                                              */
  421. /*  Parameter   :                           */
  422. /*    blocks     - total number of pixel blocks             */
  423. /*  Returns     : none                          */
  424. /*  Called by   : DFCimcomp()                       */
  425. /*  Calls       : none                          */
  426. /************************************************************************/
  427.  
  428. static void fillin_color(blocks)
  429. int blocks;
  430. {
  431.   int i, j, k;
  432.  
  433.   for (i=0; i<blocks; i++)
  434.     for (j=HI; j<=LO; j++)
  435.     {
  436.       k = indx(color_pt[2*i+j].c[RED],color_pt[2*i+j].c[GREEN],
  437.            color_pt[2*i+j].c[BLUE]);
  438.       image[i*4+2+j] = trans[k];
  439.     }
  440. } /* end of fillin_color */
  441.  
  442.  
  443.  
  444.  
  445.  
  446. /************************************************************************/
  447. /*  Function    : indx                          */
  448. /*  Purpose : Maps an rgb triple (5 bits each) to an integer array  */
  449. /*        index                         */
  450. /*  Parameter   :                           */
  451. /*    r, g, b    - color components                 */
  452. /*  Returns     : returns an array index                */
  453. /*  Called by   : set_palette(), fillin_color(), map()                  */
  454. /*  Calls       : none                          */
  455. /************************************************************************/
  456.  
  457. static int indx(r, g, b)
  458. char r, g, b;
  459. {
  460.   int temp;
  461.  
  462.   temp = 0;
  463.   temp = (r << 10) | (g  << 5) | b ;
  464.   return temp;
  465. } /* end of indx */
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472. /************************************************************************/
  473. /*  Function    : map                           */
  474. /*  Purpose : Maps a color_pt to the closest representative color   */
  475. /*        Sets up translation table             */
  476. /*  Parameter   :                           */
  477. /*    blocks     - total number of pixel blocks             */
  478. /*  Returns     : none                          */
  479. /*  Called by   : DFCimcomp()                       */
  480. /*  Calls       : nearest_color()                   */
  481. /************************************************************************/
  482.  
  483. static void map(blocks)
  484. int blocks;
  485. {
  486.   int i, k;
  487.   int r, g, b;
  488.   int indx();
  489.   int nearest_color();
  490.  
  491.   for (i=0; i<(2*blocks); i++)
  492.   {
  493.     k = indx(color_pt[i].c[RED], color_pt[i].c[GREEN], color_pt[i].c[BLUE]);
  494.  
  495.     if (trans[k] == -1)
  496.     {
  497.       r = color_pt[i].c[RED]<<3;
  498.       g = color_pt[i].c[GREEN]<<3;
  499.       b = color_pt[i].c[BLUE]<<3;
  500.       trans[k] = nearest_color(r, g, b);
  501. /*
  502.       printf("map: %d %d %d mapped to %d %d %d\n", r, g, b, new_pal[trans[k]*3],
  503.           new_pal[trans[k]*3+1], new_pal[trans[k]*3+2]);
  504. */
  505.     }
  506.   }
  507. } /* end of map */
  508.   
  509.  
  510.  
  511.  
  512. /************************************************************************/
  513. /*  Function    : nearest_color                     */
  514. /*  Purpose : Finds the nearest palette color           */
  515. /*  Parameter   :                           */
  516. /*    r, g, b    - color component                  */
  517. /*  Returns     : Entry number of the closest color in the palette      */
  518. /*  Called by   : map()                         */
  519. /*  Calls       : sqr()                         */
  520. /************************************************************************/
  521.  
  522. static int nearest_color(r, g, b)
  523. char r, g, b;
  524. {
  525.   int i, near; 
  526.   long int min, error;
  527.   long int sqr();
  528.  
  529.   min = sqr(r-new_pal[0]) + sqr(g-new_pal[1]) + sqr(b-new_pal[2]);
  530.   near = 0;
  531.   for (i=1; i<PALSIZE; i++)
  532.   {
  533.     error = sqr(r-new_pal[3*i]) + sqr(g-new_pal[3*i+1]) + 
  534.         sqr(b-new_pal[3*i+2]);
  535.     if (error < min)
  536.     {
  537.     min = error;
  538.         near = i;
  539.     }
  540.   }
  541.  
  542.   return near;
  543. } /* end of nearest_color */
  544.  
  545.  
  546.  
  547.  
  548. /************************************************************************/
  549. /*  Function    : sqr                           */
  550. /*  Purpose : Computes the square of an integer         */
  551. /*  Parameter   :                           */
  552. /*    x      - an integer                       */
  553. /*  Returns     : The square of x                   */
  554. /*  Called by   : nearest_color()                   */
  555. /*  Calls       : none                          */
  556. /************************************************************************/
  557.  
  558. static long int sqr(x)
  559. int x;
  560. {
  561.   return (x*x);
  562. }
  563.  
  564.  
  565.  
  566.  
  567.  
  568. /************************************************************************/
  569. /*  Function    : DFCunimcomp                       */
  570. /*  Purpose : 'Decompresses' the compressed image           */
  571. /*  Parameter   :                           */
  572. /*    xdim, ydim - dimensions of image                  */
  573. /*    in, out    - Input buffer and output buffer. Size of input buffer */
  574. /*         is (xdim*ydim)/4. Size of output buffer is 4 times   */
  575. /*         that. It 'restores' images into seq-type files       */
  576. /*  Returns     : none                          */
  577. /*  Called by   : External routines                 */
  578. /*  Calls       : none                          */
  579. /************************************************************************/
  580.  
  581. void DFCunimcomp(xdim, ydim, in, out)
  582. int32 xdim, ydim;
  583. char in[], out[];
  584. {
  585.   int bitmap, temp;
  586.   int i, j, k, x, y;
  587.   char hi_color, lo_color;
  588.  
  589.   for (y=0; y<(ydim/4); y++)
  590.     for (x=0; x<xdim; x=x+4)
  591.     {
  592.       k = y*xdim + x;
  593.       hi_color = in[k+2]; 
  594.       lo_color = in[k+3];
  595.  
  596.       bitmap = (in[k] << 8) | in[k+1];
  597.  
  598.       for (i=(y*4); i<(y*4+4); i++)
  599.       {
  600.         temp = bitmap >> (3 + y*4 - i)*4;
  601.         for (j=x; j<(x+4); j++)
  602.         {
  603.       if ((temp & 8) == 8)
  604.         out[i*xdim+j] = hi_color;
  605.       else
  606.         out[i*xdim+j] = lo_color;
  607.       temp = temp << 1;
  608.     }
  609.       }
  610.     } /* end of for x */
  611. } /* end of DFCunimcomp */
  612.  
  613.  
  614.  
  615. /************************************************************************/
  616. /*  Module Name : color                         */
  617. /*  Exports     : sel_palette(); new_pal, pointer to a new color palette*/
  618. /*  Purpose     : Quantizes colors                  */
  619. /*  Author  : Eng-Kiat Koh                      */
  620. /*  Date    : June 30th, 1988                   */
  621. /*  Functions   : sel_palette(), init(), sort(), partition(), find_box()*/
  622. /*        split_box(), assign_color(), select_dim(), find_med() */
  623. /*                classify(), next_pt()                                 */
  624. /************************************************************************/
  625.  
  626.  
  627.  
  628.  
  629.  
  630.  
  631.  
  632. /************************************************************************/
  633. /*  Function    : sel_palette                       */
  634. /*  Purpose : Selects PALSIZE palette colors out of a list of colors*/
  635. /*        in color_pt                       */
  636. /*  Parameter   :                           */
  637. /*    blocks     - number of pixel blocks               */
  638. /*    distinct   - number of distinct colors                */
  639. /*    color_pt   - contains the lo hi colors for each pixel block       */
  640. /*  Returns     : none                          */
  641. /*  Called by   : DFCimcomp()                       */
  642. /*  Calls       : init(), split_box(), find_box(), assign_color()   */
  643. /************************************************************************/
  644.  
  645. static void sel_palette(blocks,distinct, color_pt)
  646. int blocks, distinct;
  647. struct rgb *color_pt;
  648. {
  649.   int boxes;
  650. /*  int i, j;*/
  651.   struct box *ptr;
  652.   struct box *find_box();
  653.   void init();
  654.   void split_box();
  655.   void assign_color();
  656.  
  657.   init(blocks, distinct, color_pt);
  658.  
  659.   /* split box into smaller boxes with about equal number of points */
  660.   for (boxes=1; boxes < PALSIZE; boxes++)
  661.   {
  662. /*
  663.     ptr=frontier->right;
  664.     j = 0;
  665.     while (ptr != NULL)
  666.     {
  667.       printf("Box %d, distinct %d, total %d\n",j,ptr->nmbr_distinct,
  668.              ptr->nmbr_pts);
  669.       for (i=0; i<ptr->nmbr_distinct; i++)
  670.         printf("pt %d: %d %d %d",i,distinct_pt[ptr->pts[i]].c[RED],
  671.                 distinct_pt[ptr->pts[i]].c[GREEN], 
  672.             distinct_pt[ptr->pts[i]].c[BLUE]);
  673.       j++;
  674.       ptr = ptr->right;
  675.     }
  676. */
  677.  
  678.     ptr = find_box();
  679.     split_box(ptr);
  680.   } 
  681.  
  682.   assign_color();
  683. }
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690. /************************************************************************/
  691. /*  Function    : init                          */
  692. /*  Purpose : Initializes the global variables, sets up the first   */
  693. /*        box. It will contain all the color points     */
  694. /*  Parameter   :                           */
  695. /*    blocks     - number of pixel blocks               */
  696. /*    distinct   - number of distinct colors                */
  697. /*    color_pt   - contains the lo hi colors for each pixel block       */
  698. /*  Returns     : none                          */
  699. /*  Called by   : sel_palette()                     */
  700. /*  Calls       : none                          */
  701. /************************************************************************/
  702.  
  703. static void init(blocks, distinct, color_pt)
  704. int blocks, distinct;
  705. struct rgb *color_pt;
  706. {
  707.   int i, j, k, l;
  708.   int temp[MAXCOLOR];
  709.   struct box *first;
  710.   struct box *dummy;
  711.  
  712.   /* alloc memory */
  713.   hist = (int *)calloc((unsigned)distinct,sizeof(int));
  714.   distinct_pt = (struct rgb *)calloc((unsigned)distinct,sizeof(struct rgb));
  715.  
  716.   for (i=0; i<distinct; i++)
  717.     hist[i] = 0;
  718.  
  719.  
  720.   /* select distinct pts and set up histogram */
  721.   for (i=0; i<MAXCOLOR; i++)
  722.     temp[i] = -1;
  723.  
  724.   k = 0;
  725.   for (i=0; i<(2*blocks); i++)
  726.   {
  727.     j = (color_pt[i].c[RED] << 10) | (color_pt[i].c[GREEN] << 5) |
  728.         color_pt[i].c[BLUE];
  729.  
  730.     if (temp[j] == -1)
  731.     {
  732.       /* new pt */
  733.       temp[j] = k;
  734.       for (l=RED; l<=BLUE; l++)
  735.     distinct_pt[k].c[l] = color_pt[i].c[l];
  736.       k++;
  737.    }
  738.  
  739.    hist[temp[j]]++;
  740.   }
  741.  
  742.       
  743.   /* set up first box */
  744.   first = (struct box *)malloc(sizeof(struct box));
  745.   for (i=RED; i<=BLUE; i++)
  746.   {
  747.     first->bnd[i][LO] = 999.9;
  748.     first->bnd[i][HI] = -999.9;
  749.  
  750.     for (j=0; j<distinct; j++)
  751.     {
  752.       if (first->bnd[i][LO] > (float)distinct_pt[j].c[i])
  753.     first->bnd[i][LO] = (float)distinct_pt[j].c[i];
  754.  
  755.       if (first->bnd[i][HI] < (float)distinct_pt[j].c[i])
  756.     first->bnd[i][HI] = (float)distinct_pt[j].c[i];
  757.     } /* end of for j */
  758.  
  759.     first->bnd[i][LO] = first->bnd[i][LO] - EPSILON;
  760.     first->bnd[i][HI] = first->bnd[i][HI] + EPSILON;
  761.   } /* end of for i */
  762.  
  763.   first->pts = (int *)calloc((unsigned)distinct,sizeof(int));
  764.   for (i=0; i<distinct; i++)
  765.     first->pts[i] = i;
  766.   first->nmbr_pts = 2*blocks;
  767.   first->nmbr_distinct = distinct;
  768.  
  769.   dummy = (struct box *)malloc(sizeof(struct box));
  770.   frontier = dummy;
  771.   dummy->right = first;
  772.   first->left = dummy;
  773.   first->right = NULL;
  774.   dummy->nmbr_pts = 0;
  775. } /* end of init */
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783. /************************************************************************/
  784. /*  Function    : sort                          */
  785. /*  Purpose : Performs quick sort on the points in a box along a    */
  786. /*        given dimension                   */
  787. /*  Parameter   :                           */
  788. /*    l, r   - index of leftmost and rightmost element      */
  789. /*    dim    - dimension along which sorting is done        */
  790. /*    rank   - an array which carries the index of the points to be */
  791. /*         sorted                       */
  792. /*  Returns     : none                          */
  793. /*  Called by   : find_med()                        */
  794. /*  Calls       : partition()                       */
  795. /************************************************************************/
  796.  
  797. static void sort(l,r,dim, rank)
  798. int l, r, dim, rank[];
  799. {
  800.   int i;
  801.   int partition();
  802.   void sort();
  803.  
  804.   if (r > l)
  805.   {
  806.     i = partition(l, r, dim, rank);
  807.     sort(l, i-1, dim, rank);
  808.     sort(i+1, r, dim, rank);
  809.   }
  810. }
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817. /************************************************************************/
  818. /*  Function    : partition                     */
  819. /*  Purpose : Partitions the list into 2 parts as in the quick sort */
  820. /*        algorithm                     */
  821. /*  Parameter   :                           */
  822. /*    l, r   - index of leftmost and rightmost element      */
  823. /*    dim    - dimension along which sorting is done        */
  824. /*    rank   - an array which carries the index of the points to be */
  825. /*  Returns     : index where list is partitioned           */
  826. /*  Called by   : sort()                        */
  827. /*  Calls       : none                          */
  828. /************************************************************************/
  829.  
  830. static int partition(l, r, dim, rank)
  831. int l, r, dim, rank[];
  832. {
  833.   int i, j, temp;
  834.   char v;
  835.   
  836.   v = distinct_pt[rank[r]].c[dim];
  837.   i = l-1;
  838.   j = r;
  839.  
  840.   /* repeat until i and j crosses */
  841.   do
  842.   {
  843.     /* repeat until an element >= v is found */
  844.     do
  845.       i++;
  846.     while (distinct_pt[rank[i]].c[dim] < v);
  847.  
  848.     /* repeat until an element <= v is found */
  849.     do
  850.       j--;
  851.     while ((j>0) && (distinct_pt[rank[j]].c[dim] > v));
  852.  
  853.     /* swap pointers */
  854.     temp = rank[i];
  855.     rank[i] = rank[j];
  856.     rank[j] = temp;
  857.   }
  858.   while (i < j);
  859.  
  860.   /* position partitioning element at location i */
  861.   temp = rank[j];
  862.   rank[j] = rank[i];
  863.   rank[i] = rank[r];
  864.   rank[r] = temp;
  865.  
  866.   return i;
  867. }
  868.  
  869.  
  870.  
  871.  
  872.  
  873. /************************************************************************/
  874. /*  Function    : find_box                      */
  875. /*  Purpose : Finds the box with the largest number of color points */
  876. /*        The points need not necessarily be distinct. But in   */
  877. /*        order to partition the box, there must be at least  2 */
  878. /*        distinct points                   */
  879. /*  Parameter   : none                          */
  880. /*  Returns     : pointer to box selected for splitting         */
  881. /*  Called by   : sel_palette()                     */
  882. /*  Calls       : none                          */
  883. /************************************************************************/
  884.  
  885. static struct box *find_box()
  886. {
  887.   struct box *temp;
  888.   struct box *max;
  889.   int max_pts;
  890.  
  891.   max_pts = 1;
  892.   max = NULL;
  893.   temp = frontier->right;
  894.   while (temp != NULL)
  895.     if ((temp->nmbr_distinct > 1) && (max_pts < temp->nmbr_pts))
  896.     {
  897.       max_pts = temp->nmbr_pts;
  898.       max = temp;
  899.       temp = temp->right;
  900.     }
  901.     else
  902.       temp = temp->right;
  903.  
  904.   if (max == NULL)
  905.   {
  906.     printf("Error : Number of color points < palette \n");
  907.     exit(1);
  908.   }
  909.  
  910.   return max;
  911. }
  912.  
  913.  
  914.  
  915.  
  916.  
  917. /************************************************************************/
  918. /*  Function    : split_box                     */
  919. /*  Purpose : Splits a selected box into 2 and reinserts the 2 sub- */
  920. /*        boxes into the frontier list              */
  921. /*  Parameter   :                           */
  922. /*    ptr    - pointer to box to be split               */
  923. /*  Returns     : none                          */
  924. /*  Called by   : sel_palette()                     */
  925. /*  Calls       : find_med(), select_dim(), classify()          */
  926. /************************************************************************/
  927.  
  928. static void split_box(ptr)
  929. struct box *ptr;
  930. {
  931.   int dim, j, i;
  932.   float median;
  933.   struct box *l_child, *r_child;
  934.   int select_dim();
  935.   float find_med();
  936.   void classify();
  937.   
  938.   dim = select_dim(ptr);
  939.   median = find_med(ptr, dim);
  940.  
  941.   /* create 2 child */
  942.   l_child = (struct box *)malloc(sizeof(struct box));
  943.   r_child = (struct box *)malloc(sizeof(struct box));
  944.   
  945.   for (i=RED; i<=BLUE; i++)
  946.     for (j=HI; j<=LO; j++)
  947.     {
  948.       l_child->bnd[i][j] = ptr->bnd[i][j];
  949.       r_child->bnd[i][j] = ptr->bnd[i][j];
  950.     }
  951.   l_child->bnd[dim][HI] = median;
  952.   r_child->bnd[dim][LO] = median;
  953.  
  954.   classify(ptr,l_child);
  955.   classify(ptr,r_child);
  956.  
  957.   r_child->right = ptr->right;
  958.   r_child->left = l_child;
  959.   l_child->right = r_child;
  960.   l_child->left = ptr->left;
  961.   (ptr->left)->right = l_child;
  962.   if (ptr->right != NULL)
  963.     (ptr->right)->left = r_child;
  964. } /* end of split_box */
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971. /************************************************************************/
  972. /*  Function    : assign_color                      */
  973. /*  Purpose : Assigns a color to each box. It computes the average  */
  974. /*        color of all the points in the box            */
  975. /*        Sets up the new_pal buffer. Each color component is   */
  976. /*        shifted left 3 bits because of the truncation when    */
  977. /*        color_pt was set up                   */
  978. /*  Parameter   : none                          */
  979. /*  Returns     : none                          */
  980. /*  Called by   : sel_palette()                     */
  981. /*  Calls       : none                          */
  982. /************************************************************************/
  983.  
  984.  
  985. static void assign_color()
  986. {
  987.   struct box *temp;
  988.   int ent, k, j;
  989.   int c[3];
  990.  
  991.   temp = frontier->right;
  992.   for (ent=0; ent<PALSIZE; ent++)
  993.   {
  994.     for (k=RED; k<=BLUE; k++)
  995.       c[k] = 0;
  996.  
  997. /*
  998.     printf("Box %d: number of pts %d\n", ent, temp->nmbr_pts);
  999. */
  1000.  
  1001.     for (j=0; j<temp->nmbr_distinct; j++)
  1002.     {
  1003. /*
  1004.       printf("pt %d:", j);
  1005. */
  1006.       for (k=RED; k<=BLUE; k++)
  1007.       {
  1008. /*
  1009.         printf("%d ",distinct_pt[temp->pts[j]].c[k]);
  1010. */
  1011.     c[k] = c[k] + distinct_pt[temp->pts[j]].c[k]*hist[temp->pts[j]];
  1012.       }
  1013. /*
  1014.       printf("\n");
  1015. */
  1016.     }
  1017.  
  1018.     for (k=RED; k<=BLUE; k++)
  1019.     {
  1020.       c[k] = c[k] / temp->nmbr_pts;
  1021.       new_pal[3*ent+k] = c[k] << 3;
  1022.     }
  1023.     
  1024.     temp = temp->right;
  1025.   } /* end of for entry */
  1026. }
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032. /************************************************************************/
  1033. /*  Function    : select_dim                        */
  1034. /*  Purpose : Selects the dimension with the largest spread         */
  1035. /*  Parameter   :                           */
  1036. /*    ptr    - pointer to desired box               */
  1037. /*  Returns     : dimension where the box is to be split        */
  1038. /*  Called by   : split_box()                       */
  1039. /*  Calls       : none                          */
  1040. /************************************************************************/
  1041.  
  1042. static int select_dim(ptr)
  1043. struct box *ptr;
  1044. {
  1045.   int i, j, low[3], high[3];
  1046.   int max;
  1047.  
  1048.  
  1049.   for (j=RED; j<=BLUE; j++)
  1050.   {
  1051.     low[j] = distinct_pt[ptr->pts[0]].c[j];
  1052.     high[j] = distinct_pt[ptr->pts[0]].c[j];
  1053.   }
  1054.  
  1055.   for (i=1; i<ptr->nmbr_distinct; i++)
  1056.     for (j=RED; j<=BLUE; j++)
  1057.     {
  1058.       if (low[j] > distinct_pt[ptr->pts[i]].c[j])
  1059.     low[j] = distinct_pt[ptr->pts[i]].c[j];
  1060.       if (high[j] < distinct_pt[ptr->pts[i]].c[j])
  1061.     high[j] = distinct_pt[ptr->pts[i]].c[j];
  1062.     }
  1063.  
  1064.   max = high[RED] - low[RED];
  1065.   i = RED;
  1066.   for (j=GREEN; j<=BLUE; j++)
  1067.     if (max < (high[j] - low[j]))
  1068.     {
  1069.       max = high[j] - low[j];
  1070.       i = j;
  1071.     }
  1072.  
  1073.   return i;
  1074. } /* end of select_dim */
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080. /************************************************************************/
  1081. /*  Function    : find_med                      */
  1082. /*  Purpose : Finds the point where the box is to be split. It finds*/
  1083. /*        a point such that the 2 new boxes have about the same */
  1084. /*        number of color points.               */
  1085. /*  Parameter   :                           */
  1086. /*    ptr    - pointer to box to be split               */
  1087. /*    dim    - dimension to split box               */
  1088. /*  Returns     : point where the box is to be cut          */
  1089. /*  Called by   : split_box()                       */
  1090. /*  Calls       : next_pt()                     */
  1091. /************************************************************************/
  1092.  
  1093. static float find_med(ptr,dim)
  1094. struct box *ptr;
  1095. int dim;
  1096. {
  1097.   int i, j, count, next, prev;
  1098.   int *rank;
  1099.   float median;
  1100.   int next_pt();
  1101.   void sort();
  1102.  
  1103.   rank = (int *)calloc((unsigned)ptr->nmbr_distinct,sizeof(int));
  1104.   for (i=0; i<ptr->nmbr_distinct; i++)
  1105.     rank[i] = ptr->pts[i];
  1106.  
  1107.   sort(0,ptr->nmbr_distinct-1,dim,rank);
  1108. /*
  1109.   for (i=0; i<ptr->nmbr_distinct; i++)
  1110.     printf("find_med: sorted list is %d\n",distinct_pt[rank[i]].c[dim]);
  1111. */
  1112.   
  1113.  
  1114.   count = 0;
  1115.   i = 0;
  1116.   while ((i < ptr->nmbr_distinct) && (count < ptr->nmbr_pts/2))
  1117.   {
  1118.     next = next_pt(dim, i, rank, ptr->nmbr_distinct);
  1119.     for (j=i; j<next; j++)
  1120.       count = count + hist[rank[j]];
  1121.  
  1122.     prev = i;
  1123.     i = next; 
  1124.   }
  1125.  
  1126.   if (prev == 0)
  1127.   {
  1128.     /* the first distinct point overshot the median */
  1129.     median = (float)distinct_pt[rank[prev]].c[dim] + EPSILON;
  1130.   }
  1131.   else
  1132.     median = (float)distinct_pt[rank[prev-1]].c[dim] + EPSILON;
  1133.    
  1134.  
  1135.   return median;
  1136. } /* end of find_med */
  1137.   
  1138.  
  1139.  
  1140.  
  1141.  
  1142.  
  1143. /************************************************************************/
  1144. /*  Function    : classify                      */
  1145. /*  Purpose : Looks at the color points in the parent and selects   */
  1146. /*        the points that belong to the child           */
  1147. /*  Parameter   :                           */
  1148. /*    ptr    - pointer to parent                    */
  1149. /*    child  - pointer to child box                 */
  1150. /*  Returns     : none                          */
  1151. /*  Called by   : split_box()                       */
  1152. /*  Calls       : none                          */
  1153. /************************************************************************/
  1154.  
  1155. static void classify(ptr, child)
  1156. struct box *ptr, *child;
  1157. {
  1158.   int i, j;
  1159.   int *temp;
  1160.   int distinct, total;
  1161.  
  1162.   temp = (int *)calloc((unsigned)ptr->nmbr_distinct,sizeof(int));
  1163.  
  1164.   distinct = 0;
  1165.   total = 0;
  1166.   for (i=0; i<ptr->nmbr_distinct; i++)
  1167.   {
  1168.     j = ptr->pts[i];
  1169.     if ((((float)distinct_pt[j].c[RED] >= child->bnd[RED][LO]) &&
  1170.          ((float)distinct_pt[j].c[RED] <= child->bnd[RED][HI])) &&
  1171.         (((float)distinct_pt[j].c[GREEN] >= child->bnd[GREEN][LO]) &&
  1172.          ((float)distinct_pt[j].c[GREEN] <= child->bnd[GREEN][HI])) &&
  1173.         (((float)distinct_pt[j].c[BLUE] >= child->bnd[BLUE][LO]) &&
  1174.          ((float)distinct_pt[j].c[BLUE] <= child->bnd[BLUE][HI])))
  1175.     {
  1176.       /* pt is in new box */
  1177.       temp[distinct] = j;
  1178.       distinct++;
  1179.       total = total + hist[j];
  1180.     } /* end of if */
  1181.   } /* end of for i */
  1182.  
  1183.   /* assign points */
  1184.   child->nmbr_pts = total;
  1185.   child->nmbr_distinct = distinct;
  1186.   child->pts = (int *)calloc((unsigned)distinct,sizeof(int));
  1187.   for (i=0; i<distinct; i++)
  1188.     child->pts[i] = temp[i];
  1189.  
  1190. } /* end of classify */
  1191.  
  1192.  
  1193.  
  1194.  
  1195.  
  1196. /************************************************************************/
  1197. /*  Function    : next_pt                       */
  1198. /*  Purpose : Determines the next point that has a different value  */
  1199. /*        from the current point along  a dimension     */
  1200. /*  Parameter   :                           */
  1201. /*    dim    - dimension where box is to be split           */
  1202. /*    i      - index to current point               */
  1203. /*    rank       - sorted list of points to be searched starting from i */
  1204. /*    distinct   - length of sorted list                                */
  1205. /*  Returns     : index of point that has a different value     */
  1206. /*  Called by   : find_med                      */
  1207. /*  Calls       : none                          */
  1208. /************************************************************************/
  1209.  
  1210. static int next_pt(dim, i, rank, distinct)
  1211. int dim, i, rank[], distinct;
  1212. {
  1213.   int j;
  1214.   char old;
  1215.  
  1216.   old = distinct_pt[rank[i]].c[dim];
  1217.   for (j=(i+1); j<distinct; j++)
  1218.     if (distinct_pt[rank[j]].c[dim] != old)
  1219.       break;
  1220.  
  1221.   return j;
  1222. } /* end of next_pt */
  1223.  
  1224.